﻿using System;
using Castle.ActiveRecord;
using CastleSample.Core;
using CastleSample.DataAccess.Interface;
using CastleSample.Entity;
using CastleSample.UnitTest.Common;
using NUnit.Framework;

namespace TestDataAccessAR
{
    [TestFixture]
    public class TestOrderDataService
    {
        [Test]
        public void TestCreateOrderWithoutOrderItems()
        {
            Guid orderId = CreateOrderWithoutItems();
            IOrderDataService orderDataService = ServiceLocator.Get<IOrderDataService>();

            using (TransactionScope ts = new TransactionScope(TransactionMode.New))
            {
                OrderEntity order = orderDataService.FindOrderById(orderId);
                Assert.IsNotNull(order, "Cant not retrieve the order just created");
                Assert.AreEqual(OrderStatus.New, order.Status, "The Status is not right");
                Assert.AreEqual(0, order.Version, "The Version is not right");
            }
        }

        [Test]
        public void TestCreateOrderWithOrderItems()
        {
            Guid orderId = CreateOrderWithItems();
            IOrderDataService orderDataService = ServiceLocator.Get<IOrderDataService>();

            using (TransactionScope ts = new TransactionScope(TransactionMode.New))
            {
                OrderEntity order = orderDataService.FindOrderById(orderId);
                Assert.IsNotNull(order, "Cant not retrieve the order just created");
                Assert.AreEqual(OrderStatus.New, order.Status, "The Status is not right");
                Assert.AreEqual(0, order.Version, "The Version is not right");
                Assert.AreEqual(3, order.OrderItems.Count, "The OrderItems count not right");
            }
        }

        [Test]
        public void TestUpdateOrderProperties()
        {
            Guid orderId = CreateOrderWithoutItems();
            IOrderDataService orderDataService = ServiceLocator.Get<IOrderDataService>();

            using (TransactionScope ts = new TransactionScope(TransactionMode.New))
            {
                OrderEntity order = orderDataService.FindOrderById(orderId);
                order.Version = 5;
                orderDataService.UpdateOrder(order,false);
            }

            using (TransactionScope ts = new TransactionScope(TransactionMode.New))
            {
                OrderEntity order = orderDataService.FindOrderById(orderId);
                Assert.AreEqual(5, order.Version, "The Version did not updated.");
            }
        }

        [Test]
        public void TestUpdateOrder()
        {
            // TODO: complete this complex unit test TestUpdateOrder
        }

        [Test]
        public void TestDeleteOrderById()
        {
            Guid orderId = CreateOrderWithoutItems();
            IOrderDataService orderDataService = ServiceLocator.Get<IOrderDataService>();

            using (TransactionScope ts = new TransactionScope(TransactionMode.New))
            {
                orderDataService.DeleteOrder(orderId);
            }

            using (TransactionScope ts = new TransactionScope(TransactionMode.New))
            {
                OrderEntity order = orderDataService.FindOrderById(orderId);
                Assert.IsNull(order, "Order did not deleted.");
            }
        }

        //[Test]
        //public void TestDeleteOrder()
        //{
        //    Guid orderId = CreateOrderWithoutItems();
        //    IOrderDataService orderDataService = ServiceLocator.Get<IOrderDataService>();

        //    using (TransactionScope ts = new TransactionScope(TransactionMode.New))
        //    {
        //        OrderEntity order = orderDataService.FindOrderById(orderId);
        //        Assert.IsNotNull(order, "Can not retrieve order for delete.");
        //        orderDataService.DeleteOrder(order, false);
        //    }

        //    using (TransactionScope ts = new TransactionScope(TransactionMode.New))
        //    {
        //        OrderEntity order = orderDataService.FindOrderById(orderId);
        //        Assert.IsNull(order, "Order did not deleted.");
        //    }
        //}

        private Guid CreateOrderWithoutItems()
        {
            IOrderDataService orderDataService = ServiceLocator.Get<IOrderDataService>();
            Guid orderId;
            using (TransactionScope ts = new TransactionScope(TransactionMode.New))
            {
                OrderEntity order = new OrderEntity();
                order.Status = OrderStatus.New;
                order.Version = 0;
                order.CreateDate = DateTime.Now;

                orderDataService.CreateOrder(order);
                orderId = order.OrderId;
            }

            Assert.IsNotNull(orderId, "Create order did not assign a OrderId");

            return orderId;
        }

        private Guid CreateOrderWithItems()
        {
            IOrderDataService orderDataService = ServiceLocator.Get<IOrderDataService>();

            Guid orderId;
            using (TransactionScope ts = new TransactionScope(TransactionMode.New))
            {
                OrderEntity order = new OrderEntity();
                order.Status = OrderStatus.New;
                order.Version = 0;
                order.CreateDate = DateTime.Now;

                OrderItemEntity item = new OrderItemEntity();
                item.ProductId = RandomGen.GetString("product ", 5);
                item.Quantity = RandomGen.GetInt(1, 100);
                item.Amount = RandomGen.GetInt(1, 300);
                order.OrderItems.Add(item);
                item = new OrderItemEntity();
                item.ProductId = RandomGen.GetString("product ", 5);
                item.Quantity = RandomGen.GetInt(1, 100);
                item.Amount = RandomGen.GetInt(1, 300);
                order.OrderItems.Add(item);
                item = new OrderItemEntity();
                item.ProductId = RandomGen.GetString("product ", 5);
                item.Quantity = RandomGen.GetInt(1, 100);
                item.Amount = RandomGen.GetInt(1, 300);
                order.OrderItems.Add(item);

                orderDataService.CreateOrder(order);
                orderId = order.OrderId;
            }

            Assert.IsNotNull(orderId, "Create order did not assign a OrderId");
            return orderId;
        }
    }
}